package com.gxc.array;

/**
 * 1958. 检查操作是否合法
 给你一个下标从 0 开始的 8 x 8 网格 board ，
 其中 board[r][c] 表示游戏棋盘上的格子 (r, c) 。
 棋盘上空格用 '.' 表示，白色格子用 'W' 表示，黑色格子用 'B' 表示。

 游戏中每次操作步骤为：选择一个空格子，将它变成你正在执行的颜色（要么白色，要么黑色）。
 但是，合法 操作必须满足：涂色后这个格子是 好线段的一个端点 （好线段可以是水平的，竖直的或者是对角线）。

 好线段 指的是一个包含 三个或者更多格子（包含端点格子）的线段，线段两个端点格子为 同一种颜色 ，
 且中间剩余格子的颜色都为 另一种颜色 （线段上不能有任何空格子）。你可以在下图找到好线段的例子：


 给你两个整数 rMove 和 cMove 以及一个字符 color ，
 表示你正在执行操作的颜色（白或者黑），如果将格子 (rMove, cMove) 变成颜色 color 后，是一个 合法 操作，
 那么返回 true ，
 如果不是合法操作返回 false 。
 */
public class CheckMove {

    public static void main(String[] args) {
        char[][] a = new char[][]{{'.','.','.','B','.','.','.','.'},{'.','.','.','W','.','.','.','.'},{'.','.','.','W','.','.','.','.'},{'.','.','.','W','.','.','.','.'},{'W','B','B','.','W','W','W','B'},{'.','.','.','B','.','.','.','.'},{'.','.','.','B','.','.','.','.'},{'.','.','.','W','.','.','.','.'}};
        System.out.println(handle(a, 4, 3, 'B'));

        char[][] b = new char[][]{{'.','.','.','.','.','.','.','.'},{'.','B','.','.','W','.','.','.'},{'.','.','W','.','.','.','.','.'},{'.','.','.','W','B','.','.','.'},{'.','.','.','.','.','.','.','.'},{'.','.','.','.','B','W','.','.'},{'.','.','.','.','.','.','W','.'},{'.','.','.','.','.','.','.','B'}};
        System.out.println(handle(b, 4, 4, 'W'));
    }

    public static boolean handle(char[][] board, int rMove, int cMove, char color) {
        board[rMove][cMove] = color;
        return rightMove(board, rMove, cMove) || leftMove(board, rMove, cMove)
                || downMove(board, rMove, cMove) || upMove(board, rMove, cMove)
                || lowerRight(board, rMove, cMove) || lowerLeft(board, rMove, cMove)
                || upperLeft(board, rMove, cMove) ||upperRight(board, rMove, cMove);
    }

    private static boolean upperRight(char[][] board, int rMove, int cMove) {
        if (rMove==0  || cMove==7) return false;
        int r = rMove-1;
        int c = cMove+1;
        if (board[r][c] != board[rMove][cMove]) {
            while (r>=0 && c<8) {
                if (board[r][c] == board[rMove][cMove]) return true;
                if (board[r][c] == '.') return false;
                r--;
                c++;
            }
        } else {
            return false;
        }
        return false;
    }

    private static boolean upperLeft(char[][] board, int rMove, int cMove) {
        if (rMove==0 || cMove==0 ) return false;
        int r = rMove-1;
        int c = cMove-1;
        if (board[r][c] != board[rMove][cMove]) {
            while (r>=0 && c>=0) {
                if (board[r][c] == board[rMove][cMove]) return true;
                if (board[r][c] == '.') return false;
                r--;
                c--;
            }
        } else {
            return false;
        }
        return false;
    }


    private static boolean lowerLeft(char[][] board, int rMove, int cMove) {
        if ( cMove==0 || rMove==7 ) return false;
        int r = rMove+1;
        int c = cMove-1;
        if (board[r][c] != board[rMove][cMove]) {
            while (r<8 && c>=0) {
                if (board[r][c] == board[rMove][cMove]) return true;
                if (board[r][c] == '.') return false;
                r++;
                c--;
            }
        } else {
            return false;
        }
        return false;
    }

    private static boolean lowerRight(char[][] board, int rMove, int cMove) {
        if (rMove==7 || cMove==7) return false;
        int r = rMove+1;
        int c = cMove+1;
        if (board[r][c] != board[rMove][cMove]) {
            while (r<8 && c<8) {
                if (board[r][c] == board[rMove][cMove]) return true;
                if (board[r][c] == '.') return false;
                r++;
                c++;
            }
        } else {
            return false;
        }
        return false;
    }

    private static boolean downMove(char[][] board, int rMove, int cMove) {
        if ( rMove==7 ) return false;
        int r = rMove+1;
        if (board[r][cMove] != board[rMove][cMove]) {
            while (r<8) {
                if (board[r][cMove] == board[rMove][cMove]) return true;
                if (board[r][cMove] == '.') return false;
                r++;
            }
        } else {
            return false;
        }
        return false;
    }

    private static boolean upMove(char[][] board, int rMove, int cMove) {
        if ( rMove==0) return false;
        int r = rMove-1;
        if (board[r][cMove] != board[rMove][cMove]) {
            while (r>=0) {
                if (board[r][cMove] == board[rMove][cMove]) return true;
                if (board[r][cMove] == '.') return false;
                r--;
            }
        } else {
            return false;
        }
        return false;
    }

    private static boolean rightMove(char[][] board, int rMove, int cMove) {
        if (cMove==7) return false;
        int c = cMove+1;
        if (board[rMove][c] != board[rMove][cMove]) {
            while (c<8) {
                if (board[rMove][c] == board[rMove][cMove]) return true;
                if (board[rMove][c] == '.') return false;
                c++;
            }
        } else {
            return false;
        }
        return false;
    }

    private static boolean leftMove(char[][] board, int rMove, int cMove) {
        if (cMove==0) return false;
        int c = cMove-1;
        if (board[rMove][c] != board[rMove][cMove]) {
            while (c>=0) {
                if (board[rMove][c] == board[rMove][cMove]) return true;
                if (board[rMove][c] == '.') return false;
                c--;
            }
        } else {
            return false;
        }
        return false;
    }

    /**
     * 用数组来代替每行的改变量
     */
    class Solution {
        public boolean checkMove(char[][] board, int rMove, int cMove, char color) {
            // 从 x 轴正方向开始逆时针枚举 8 个方向
            int[] dx = {1, 1, 0, -1, -1, -1, 0, 1};   // 行改变量
            int[] dy = {0, 1, 1, 1, 0, -1, -1, -1};   // 列改变量
            for (int k = 0; k < 8; ++k) {
                if (check(board, rMove, cMove, color, dx[k], dy[k])) {
                    return true;
                }
            }
            return false;
        }

        // 判断每个方向是否存在以操作位置为起点的好线段
        public boolean check(char[][] board, int rMove, int cMove, char color, int dx, int dy) {
            int x = rMove + dx;
            int y = cMove + dy;
            int step = 1;   // 当前遍历到的节点序号
            while (x >= 0 && x < 8 && y >= 0 && y < 8) {
                if (step == 1) {
                    // 第一个点必须为相反颜色
                    if (board[x][y] == '.' || board[x][y] == color) {
                        return false;
                    }
                } else {
                    // 好线段中不应存在空格子
                    if (board[x][y] == '.') {
                        return false;
                    }
                    // 遍历到好线段的终点，返回 true
                    if (board[x][y] == color) {
                        return true;
                    }
                }
                ++step;
                x += dx;
                y += dy;
            }
            // 不存在符合要求的好线段
            return false;
        }
    }


}
